package com.example.pt.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.pt.entity.TorrentInfoHash;
import com.example.pt.entity.TorrentSeedStats;
import com.example.pt.entity.UserSeedStats;
import com.example.pt.entity.UserTransferStats;
import com.example.pt.mapper.UserSeedStatsMapper;
import com.example.pt.mapper.UserTransferStatsMapper;
import com.example.pt.service.TorrentInfoHashService;
import com.example.pt.service.TorrentSeedStatsService;
import com.example.pt.service.UserSeedStatsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class UserSeedStatsServiceImpl extends ServiceImpl<UserSeedStatsMapper, UserSeedStats> implements UserSeedStatsService {
    
    private static final Logger logger = LoggerFactory.getLogger(UserSeedStatsServiceImpl.class);
    
    // 定义做种中断的时间阈值（24小时）
    private static final long SEEDING_BREAK_THRESHOLD_MILLIS = TimeUnit.HOURS.toMillis(24);
    
    @Autowired
    private TorrentSeedStatsService torrentSeedStatsService;
    
    @Autowired
    private UserTransferStatsMapper userTransferStatsMapper;
    
    @Autowired
    private TorrentInfoHashService torrentInfoHashService;
    
    /**
     * 更新用户保种统计 - 基于现有的传输数据和种子数据更新
     * 每24小时执行一次
     */
    @Override
    @Scheduled(fixedRate = 86400000) // 每24小时执行一次
    @Transactional
    public void updateAllUserSeedStats() {
        logger.info("开始更新所有用户的保种统计数据");
        
        try {
            // 1. 获取所有种子的做种统计信息，转为Map便于查询
            List<TorrentSeedStats> allSeedStats = torrentSeedStatsService.list();
            Map<String, TorrentSeedStats> seedStatsMap = allSeedStats.stream()
                    .collect(Collectors.toMap(TorrentSeedStats::getInfoHash, stats -> stats));
            
            // 2. 获取所有用户的传输统计数据
            List<UserTransferStats> allTransferStats = userTransferStatsMapper.selectList(null);
            
            // 3. 遍历每条传输统计记录，更新或创建保种统计
            for (UserTransferStats transferStats : allTransferStats) {
                updateSeedStatsFromTransfer(transferStats, seedStatsMap);
            }
            
            logger.info("完成所有用户的保种统计数据更新");
        } catch (Exception e) {
            logger.error("更新用户保种统计数据时发生错误: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 根据传输统计记录更新保种统计
     */
    private void updateSeedStatsFromTransfer(UserTransferStats transferStats, Map<String, TorrentSeedStats> seedStatsMap) {
        String infoHash = transferStats.getInfoHash();
        Integer userId = transferStats.getUserId();
        
        if (infoHash == null || infoHash.isEmpty() || userId == null) {
            return;
        }
        
        // 查询是否已有保种记录
        UserSeedStats existingStats = baseMapper.getUserSeedStatsByInfoHash(userId, infoHash);
        Date now = new Date();
        
        // 获取稀缺性系数
        double scarcityFactor = calculateScarcityFactor(infoHash, seedStatsMap);
        
        // 判断用户是否在做种 (如果上传量大于0且最后更新时间在过去24小时内)
        boolean isActiveSeeding = transferStats.getUploaded() > 0 && 
                (System.currentTimeMillis() - transferStats.getLastUpdated() < SEEDING_BREAK_THRESHOLD_MILLIS);
        
        if (existingStats != null) {
            // 获取上次的做种状态
            boolean wasActiveSeeding = existingStats.getStatus() == 0;
            
            // 如果之前是停止状态(status=1)，现在是活跃状态，说明是重新开始做种
            if (!wasActiveSeeding && isActiveSeeding) {
                logger.info("用户{}重新开始做种种子{}", userId, infoHash);
                
                // 重新开始做种时，更新开始时间为当前时间
                existingStats.setStartTime(new Date(transferStats.getLastUpdated()));
                existingStats.setLastActiveTime(new Date(transferStats.getLastUpdated()));
                
                // 状态改为做种中
                existingStats.setStatus(0);
            } 
            // 如果之前是活跃状态，现在也是活跃状态，则累计做种时间
            else if (wasActiveSeeding && isActiveSeeding) {
                // 更新最后活跃时间
                existingStats.setLastActiveTime(new Date(transferStats.getLastUpdated()));
                
                // 计算这次更新的做种天数增量(从上次更新到现在)
                long lastActiveTime = existingStats.getLastActiveTime().getTime();
                Date lastUpdateTime = existingStats.getLastActiveTime(); // 上次活跃时间
                long currentTimeMillis = transferStats.getLastUpdated();
                
                // 计算时间差（确保不会出现负值）
                long timeDiffMillis = Math.max(0, currentTimeMillis - lastUpdateTime.getTime());
                
                // 将时间差转换为天数并累加到总做种天数
                int additionalDays = (int) TimeUnit.DAYS.convert(timeDiffMillis, TimeUnit.MILLISECONDS);
                int currentSeedDays = existingStats.getSeedDays() != null ? existingStats.getSeedDays() : 0;
                existingStats.setSeedDays(currentSeedDays + additionalDays);
                
                logger.debug("用户{}种子{}累计做种天数更新: +{}天, 总计{}天", 
                        userId, infoHash, additionalDays, currentSeedDays + additionalDays);
            }
            // 如果之前是活跃状态，现在变为非活跃状态，标记为停止做种
            else if (wasActiveSeeding && !isActiveSeeding) {
                logger.info("用户{}停止做种种子{}", userId, infoHash);
                
                // 计算最后一段做种时间并累加
                Date lastUpdateTime = existingStats.getLastActiveTime();
                long lastUpdateTimeMillis = lastUpdateTime.getTime();
                long currentTimeMillis = System.currentTimeMillis();
                
                // 使用最后活跃时间作为结束时间，而不是当前时间
                long lastActiveTimeMillis = transferStats.getLastUpdated();
                
                // 计算时间差
                long timeDiffMillis = Math.max(0, lastActiveTimeMillis - lastUpdateTimeMillis);
                
                // 将时间差转换为天数并累加到总做种天数
                int additionalDays = (int) TimeUnit.DAYS.convert(timeDiffMillis, TimeUnit.MILLISECONDS);
                int currentSeedDays = existingStats.getSeedDays() != null ? existingStats.getSeedDays() : 0;
                existingStats.setSeedDays(currentSeedDays + additionalDays);
                
                // 标记为已停止做种
                existingStats.setStatus(1);
                
                logger.debug("用户{}种子{}停止做种，最后一段做种时间: +{}天, 总计{}天", 
                        userId, infoHash, additionalDays, currentSeedDays + additionalDays);
            }
            
            // 更新稀缺性系数
            existingStats.setScarcityFactor(scarcityFactor);
            
            // 计算保种积分
            int seedPoints = calculateSeedPoints(existingStats);
            existingStats.setSeedPoints(seedPoints);
            
            updateById(existingStats);
        } else if (isActiveSeeding) {
            // 创建新记录 (仅为活跃做种用户创建)
            UserSeedStats newStats = new UserSeedStats();
            newStats.setUserId(userId);
            newStats.setInfoHash(infoHash);
            newStats.setStartTime(new Date(transferStats.getLastUpdated())); // 使用最后更新时间作为开始时间
            newStats.setLastActiveTime(new Date(transferStats.getLastUpdated()));
            newStats.setSeedDays(0); // 初始保种天数为0
            newStats.setScarcityFactor(scarcityFactor);
            newStats.setSeedPoints(0); // 初始保种积分为0
            newStats.setStatus(0); // 正在做种
            
            save(newStats);
            logger.info("为用户{}创建新的保种记录: 种子{}", userId, infoHash);
        }
    }
    
    @Override
    @Transactional
    public boolean updateUserSeedStats(Integer userId, String infoHash) {
        if (userId == null || infoHash == null || infoHash.isEmpty()) {
            logger.error("更新用户保种统计失败：用户ID或种子哈希为空");
            return false;
        }
        
        // 获取用户传输统计信息
        LambdaQueryWrapper<UserTransferStats> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserTransferStats::getUserId, userId)
                    .eq(UserTransferStats::getInfoHash, infoHash);
        UserTransferStats transferStats = userTransferStatsMapper.selectOne(queryWrapper);
        
        if (transferStats == null) {
            logger.error("更新用户保种统计失败：未找到用户传输记录, userId={}, infoHash={}", userId, infoHash);
            return false;
        }
        
        // 获取所有种子的做种统计信息
        List<TorrentSeedStats> allSeedStats = torrentSeedStatsService.list();
        Map<String, TorrentSeedStats> seedStatsMap = allSeedStats.stream()
                .collect(Collectors.toMap(TorrentSeedStats::getInfoHash, stats -> stats));
        
        // 更新保种统计
        updateSeedStatsFromTransfer(transferStats, seedStatsMap);
        
        return true;
    }
    
    @Override
    public double calculateScarcityFactor(String infoHash) {
        return calculateScarcityFactor(infoHash, null);
    }
    
    /**
     * 计算种子的稀缺性系数
     * @param infoHash 种子哈希
     * @param seedStatsMap 可选的种子统计缓存Map
     * @return 稀缺性系数
     */
    private double calculateScarcityFactor(String infoHash, Map<String, TorrentSeedStats> seedStatsMap) {
        TorrentSeedStats seedStats;
        
        if (seedStatsMap != null && seedStatsMap.containsKey(infoHash)) {
            seedStats = seedStatsMap.get(infoHash);
        } else {
            seedStats = torrentSeedStatsService.getStatsByInfoHash(infoHash);
        }
        
        if (seedStats == null) {
            return 1.0; // 默认系数
        }
        
        int seeders = seedStats.getSeeders();
        
        // 根据做种人数确定稀缺性系数
        if (seeders <= 2) {
            return 2.0; // 稀缺性高
        } else if (seeders <= 5) {
            return 1.5; // 稀缺性中
        } else {
            return 1.0; // 稀缺性低
        }
    }
    
    @Override
    public List<UserSeedStats> getUserSeedStatsList(Integer userId) {
        if (userId == null) {
            return null;
        }
        return baseMapper.getUserSeedStats(userId);
    }
    
    @Override
    public int getTotalSeedPoints(Integer userId) {
        if (userId == null) {
            return 0;
        }
        Integer points = baseMapper.getTotalSeedPoints(userId);
        return points == null ? 0 : points;
    }
    
    @Override
    public int calculateSeedPoints(UserSeedStats seedStats) {
        if (seedStats == null || seedStats.getSeedDays() == null || seedStats.getScarcityFactor() == null) {
            return 0;
        }
        
        int seedDays = seedStats.getSeedDays();
        double scarcityFactor = seedStats.getScarcityFactor();
        
        // 只有保种时间超过3天才开始计算积分
        if (seedDays <= 3) {
            return 0;
        }
        
        // 保种积分 = (保种天数 - 3) * 稀缺性系数
        return (int)((seedDays - 3) * scarcityFactor);
    }
} 